/* EasyWay Game Engine
 * Copyright (C) 2006 Daniele Paggi.
 *  
 * Written by: 2006 Daniele Paggi<dshnt@hotmail.com>
 *   
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public License
 * as published by the Free Software Foundation; either version 2 of
 * the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Library General Public License for more details.
 * 
 * You should have received a copy of the GNU Library General Public
 * License along with this program; if not, write to the Free Software
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */
package org.easyway.effects.translator;

import java.nio.ByteBuffer;
import java.nio.IntBuffer;

import org.easyway.annotations.Optimized;
import org.easyway.interfaces.extended.IDrawing;
import org.easyway.interfaces.extended.ILayerID;
import org.easyway.objects.BaseObject;
import org.easyway.objects.texture.TextureCompact;
import org.easyway.objects.texture.TextureFBO;
import org.easyway.system.StaticRef;
import org.easyway.system.state.OpenGLState;
import org.easyway.utils.ImageUtils;
import org.lwjgl.BufferUtils;
import org.lwjgl.opengl.GL11;

@Optimized
public class HorizontalStripesOut extends BaseObject implements IDrawing,
		ILayerID {

	/**
	 * autogenerated serial version of class
	 */
	private static final long serialVersionUID = -6153780179551377417L;

	private int layer;

	/**
	 * the drawing sheet
	 */
	private int idLayer = -1;

	protected int mask_id;

	protected float x;

	protected TextureCompact texture;

	protected TextureCompact texture2;

	int size;

	long time;

	public HorizontalStripesOut(int size, long time) {
		if (!TextureFBO.checkFBOSupport())
			return;
		this.size = size;
		this.time = time * 1000000;
		IntBuffer stripped = makeStripped();

		// take a screenshot ------

		// texture = ImageUtils.getScreenShot();
		texture = ImageUtils.makeTexture(StaticRef.getCamera().getWidth(),
				StaticRef.getCamera().getHeight());
		texture2 = ImageUtils.makeTexture(StaticRef.getCamera().getWidth(),
				StaticRef.getCamera().getHeight());
		// texture2 = ImageUtils.getScreenShot();
		TextureCompact screen = ImageUtils.getScreenShot();
		// draw ---
		TextureFBO dinamicTexture = new TextureFBO(texture);
		dinamicTexture.startDrawing();
		{
			// --------------- draw strip ------------------
			GL11.glDisable(GL11.GL_TEXTURE_2D);
			GL11.glEnable(GL11.GL_TEXTURE_1D);
			GL11.glBindTexture(GL11.GL_TEXTURE_1D, mask_id);
			GL11.glBegin(GL11.GL_QUADS);
			GL11.glTexCoord1f(0);
			GL11.glVertex2f(0, 0);
			GL11.glVertex2f(StaticRef.getCamera().getWidth(), 0);
			GL11.glTexCoord1f(1);
			GL11.glVertex2f(StaticRef.getCamera().getWidth(), StaticRef.getCamera()
					.getHeight());
			GL11.glVertex2f(0, StaticRef.getCamera().getHeight());
			GL11.glEnd();
			// --------------- draw background ------------------
			GL11.glDisable(GL11.GL_TEXTURE_1D);
			GL11.glEnable(GL11.GL_TEXTURE_2D);
			GL11.glColorMask(true, true, true, false);
			// draw
			GL11.glBegin(GL11.GL_QUADS);
			GL11.glTexCoord2f(0, screen.yEnd);
			GL11.glVertex2f(0, 0);
			GL11.glTexCoord2f(screen.xEnd, screen.yEnd);
			GL11.glVertex2f(StaticRef.getCamera().getWidth(), 0);
			GL11.glTexCoord2f(screen.xEnd, 0);
			GL11.glVertex2f(StaticRef.getCamera().getWidth(), StaticRef.getCamera()
					.getHeight());
			GL11.glTexCoord2f(0, 0);
			GL11.glVertex2f(0, StaticRef.getCamera().getHeight());
			GL11.glEnd();
			GL11.glColorMask(true, true, true, true);
		}
		dinamicTexture.endDrawing();

		TextureFBO dinamicTexture2 = new TextureFBO(texture2);
		dinamicTexture2.startDrawing();
		{
			// --------------- draw strip ------------------
			GL11.glDisable(GL11.GL_TEXTURE_2D);
			GL11.glEnable(GL11.GL_TEXTURE_1D);
			GL11.glBindTexture(GL11.GL_TEXTURE_1D, mask_id);

			GL11.glBegin(GL11.GL_QUADS);
			GL11.glTexCoord1f(0);// (float) size /
			// StaticRef.getCamera().getHeight());
			GL11.glVertex2f(0, 0);
			GL11.glVertex2f(StaticRef.getCamera().getWidth(), 0);
			GL11.glTexCoord1f(1);// 1 + (float) size /
			// StaticRef.getCamera().getHeight());
			GL11.glVertex2f(StaticRef.getCamera().getWidth(), StaticRef.getCamera()
					.getHeight());
			GL11.glVertex2f(0, StaticRef.getCamera().getHeight());
			GL11.glEnd();
			// --------------- draw background ------------------
			GL11.glDisable(GL11.GL_TEXTURE_1D);
			GL11.glEnable(GL11.GL_TEXTURE_2D);
			GL11.glColorMask(true, true, true, false);
			// draw
			GL11.glBegin(GL11.GL_QUADS);
			GL11.glTexCoord2f(0, screen.yEnd);
			GL11.glVertex2f(0, 0);
			GL11.glTexCoord2f(screen.xEnd, screen.yEnd);
			GL11.glVertex2f(StaticRef.getCamera().getWidth(), 0);
			GL11.glTexCoord2f(screen.xEnd, 0);
			GL11.glVertex2f(StaticRef.getCamera().getWidth(), StaticRef.getCamera()
					.getHeight());
			GL11.glTexCoord2f(0, 0);
			GL11.glVertex2f(0, StaticRef.getCamera().getHeight());
			GL11.glEnd();
			GL11.glColorMask(true, true, true, true);
		}
		dinamicTexture2.endDrawing();

		GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);

		// finalization
		screen.destroy();
		GL11.glDeleteTextures(stripped);
	}

	private IntBuffer makeStripped() {
		IntBuffer buf = BufferUtils.createIntBuffer(4);
		GL11.glGenTextures(buf);
		ByteBuffer data = BufferUtils.createByteBuffer(StaticRef.getCamera()
				.getHeight() * 4);
		boolean step = true;
		int val = 0;
		for (int i = 0; i < StaticRef.getCamera().getHeight(); ++i) {
			if (i % size == 0) {
				step = !step;
				if (step)
					val = 0;
				else
					val = 255;
			}
			data.put((byte) 255);
			data.put((byte) 255);
			data.put((byte) 255);
			data.put((byte) val);
		}
		data.rewind();
		GL11.glBindTexture(GL11.GL_TEXTURE_1D, mask_id = buf.get(0));
		GL11.glTexParameteri(GL11.GL_TEXTURE_1D, GL11.GL_TEXTURE_MIN_FILTER,
				GL11.GL_LINEAR);
		GL11.glTexParameteri(GL11.GL_TEXTURE_1D, GL11.GL_TEXTURE_MAG_FILTER,
				GL11.GL_LINEAR);
		GL11.glTexParameteri(GL11.GL_TEXTURE_1D, GL11.GL_TEXTURE_WRAP_S,
				GL11.GL_CLAMP);

		GL11.glTexImage1D(GL11.GL_TEXTURE_1D, 0, GL11.GL_RGBA, StaticRef.getCamera()
				.getHeight(), 0, GL11.GL_RGBA, GL11.GL_UNSIGNED_BYTE, data);
		return buf;
	}

	public HorizontalStripesOut(int idLayer) {
		super();
		StaticRef.layers[idLayer].add(this);
	}

	public int getLayer() {
		return layer;
	}

	public void setLayer(int layer) {
		this.layer = layer;
	}

	public void render() {
		float step = (float) ((float) StaticRef.core.getElaspedTime() / (float) time);
		x += step * texture.width;
		texture.bind();
		OpenGLState.disableBlending();
		OpenGLState.enableAlphaTest();
		// draw
		GL11.glBegin(GL11.GL_QUADS);
		GL11.glTexCoord2f(0, texture.yEnd);
		GL11.glVertex2f(x, 0);
		GL11.glTexCoord2f(texture.xEnd, texture.yEnd);
		GL11.glVertex2f(x + StaticRef.getCamera().getWidth(), 0);
		GL11.glTexCoord2f(texture.xEnd, 0);
		GL11.glVertex2f(x + StaticRef.getCamera().getWidth(), StaticRef.getCamera()
				.getHeight());
		GL11.glTexCoord2f(0, 0);
		GL11.glVertex2f(x, StaticRef.getCamera().getHeight());
		GL11.glEnd();

		texture2.bind();
		// GL11.glEnable(GL11.GL_ALPHA_TEST);
		GL11.glAlphaFunc(GL11.GL_LESS, 1f);

		GL11.glBegin(GL11.GL_QUADS);
		GL11.glTexCoord2f(0, texture.yEnd);
		GL11.glVertex2f(-x, 0);
		GL11.glTexCoord2f(texture.xEnd, texture.yEnd);
		GL11.glVertex2f(-x + StaticRef.getCamera().getWidth(), 0);
		GL11.glTexCoord2f(texture.xEnd, 0);
		GL11.glVertex2f(-x + StaticRef.getCamera().getWidth(), StaticRef.getCamera()
				.getHeight());
		GL11.glTexCoord2f(0, 0);
		GL11.glVertex2f(-x, StaticRef.getCamera().getHeight());
		GL11.glEnd();
		GL11.glAlphaFunc(GL11.GL_GREATER, 0f);
		// GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
	}

	// -----------------------------------------------------------------
	// ---------------------------- IDLAYER-----------------------------
	// -----------------------------------------------------------------

	public int getIdLayer() {
		return idLayer;
	}

	public void setIdLayer(int id) {
		if (idLayer != -1) {
			StaticRef.layers[idLayer].remove(this);
		}
		if (id < 0) {
			id = 0;
		} else if (id > StaticRef.layers.length) {
			id = StaticRef.layers.length;
		}
		idLayer = id;
		StaticRef.layers[idLayer].add(this);
	}

}
